package com.guardchina.framework.auth.jwt;

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.JWTVerifyException;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.DeserializationFeature;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
import com.guardchina.framework.auth.properties.JwtProperties;
import com.guardchina.framework.util.exception.BusinessException;
import com.guardchina.framework.util.exception.login.TokenInvalidException;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.HashMap;
import java.util.Map;

/**
 * 描述：json web token工具类
 *
 * @author lwb
 * @date 2019/3/19 11:57
 */
@Slf4j
public class JsonWebToken {

    private static final String PAYLOAD = "payload";

    private JwtProperties properties;

    public JsonWebToken(JwtProperties properties){
        this.properties = properties;
    }

    public String createToken(Object object){
        final JWTSigner jwtSigner = new JWTSigner(properties.getSecret());

        final Map<String, Object> claims = new HashMap<>(1);

        ObjectMapper objectMapper = new ObjectMapper();
        try {
            claims.put(PAYLOAD, objectMapper.writeValueAsString(object));
        } catch (IOException e) {
            throw new BusinessException("生成token失败", e);
        }

        return jwtSigner.sign(claims);

    }

    public <T> T verify(String token, Class<T> clazz){
        final JWTVerifier verifier = new JWTVerifier(properties.getSecret());

        Map<String, Object> claims;

        try {
            claims = verifier.verify(token);
        } catch (SignatureException e){
            throw new TokenInvalidException("无效的token", String.format("token[%s]", token), e);
        } catch (NoSuchAlgorithmException | IOException | JWTVerifyException | InvalidKeyException e) {
            throw new BusinessException("token解析异常",String.format("token[%s]", token), e);
        }

        String json = (String) claims.get(PAYLOAD);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new BusinessException("token解析异常",String.format("json[%s], clazz[%s]", json, clazz.getName()), e);
        }
    }


}
